package com.homelink.android.explorerup;

import java.io.File;
import java.util.Stack;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ViewFlipper;

import com.homelink.android.explorerup.activity.ContentMenuActivity;
import com.homelink.android.explorerup.activity.FavorActivity;
import com.homelink.android.explorerup.activity.NewFilesActivity;
import com.homelink.android.explorerup.adapter.BaseFileListAdapter;
import com.homelink.android.explorerup.adapter.BaseFileListAdapter.ViewHolder;
import com.homelink.android.explorerup.adapter.SimpleFileListAdapter;
import com.homelink.android.explorerup.component.Dialog;
import com.homelink.android.explorerup.component.FileDetails;
import com.homelink.android.explorerup.component.PathAdapter;
import com.homelink.android.explorerup.component.ReadDirTask;
import com.homelink.android.explorerup.component.ReadDirTask.ReadDirListener;
import com.homelink.android.explorerup.db.Bookmark;
import com.homelink.android.explorerup.db.DBUtil;
import com.homelink.android.util.FileTypes;

/**
 * 
 * @author hliang@126.com
 *
 */
public class ExplorerUpActivity extends Activity implements
		View.OnClickListener, ReadDirListener, View.OnLongClickListener,
		OnTouchListener, Dialog.Listener {
	private static final String TAG = "ExplorerUp";
	private static final String ROOT_PATH = "/sdcard";
	private static final int TAG_CONTROL_NAVI = 1;
	private static final int TAG_CONTROL_SEARCH = 2;
	private static final int COUNT_MAX_HISTORY = 10;
	public static final int MSG_HIDE_NAVI_IMAGE = 1;
	public static final int DIALOG_CONFIRM_EXIT = 1;
	public static final int DIALOG_CONTEXT_MENU = 2;
	public static final int DIALOG_NEXT_FILE = 3;
	public static final String TAG_NEW_DIR = "NEW_DIR";
	public static final String TAG_NEW_FILE = "NEW_FILE";

	private String mCurrentPath;
	private SimpleFileListAdapter mFileAdaper;
	private PathAdapter mPathAdapter;
	private HorizontalScrollView mViewPathScrollView;
	private ListView mDirList;
	private LinearLayout mLayoutPathLayout;
	private ViewFlipper mViewTitleBar;
	private View mViewNavibar;
	private View mViewSearchBar;
	private View mBtnSearch;
	private Stack<String> mPathBackHistory = null;
	private Stack<String> mPathForwardHistory = null;
	private float mOnTouchX = 0;
	private float mOnTouchY = 0;
	private boolean mIsTouchOnce = false;
	private ImageView mNaviImage;
	private int mNaviImageAlpah = 255;
	private Handler mHandler = null;
	private int mCurrentSelectedIndex = -1;
	private boolean mIsNaviImageHide = true;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);

		setContentView(R.layout.main);
		initGlobalView();
		initLocalView();
		Log.d(TAG, "onCreate");

		// EditText t ;

	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_search:
			ImageButton btn = (ImageButton) mBtnSearch;
			Integer tag = (Integer) btn.getTag();
			if (tag == TAG_CONTROL_NAVI) {
				btn.setImageResource(R.drawable.search_64);
				btn.setTag(TAG_CONTROL_SEARCH);
				mViewTitleBar.showNext();
				item.setTitle(R.string.menu_filter);
				item.setIcon(R.drawable.filter_64);
			} else {
				btn.setImageResource(R.drawable.filter_64);
				btn.setTag(TAG_CONTROL_NAVI);
				mViewTitleBar.showPrevious();
				item.setTitle(R.string.menu_search);
				item.setIcon(R.drawable.search_64);

			}

			break;
		case R.id.menu_select:
			mFileAdaper.setSelectEnable(!mFileAdaper.isSelectEnable());
			// mFileAdaper.notifyDataSetChanged();
			break;
		case R.id.menu_exit:
			finish();
			break;
		case R.id.menu_new:
			onNewFile(true);
			break;
		case R.id.menu_favor:
			Intent i = new Intent(this,FavorActivity.class);
			startActivity(i);
			break;
		}

		return false;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		Log.d(TAG, "onKeyDown....");
		if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
			if (!naviHistoryPath(true)) {
				this.showDialog(DIALOG_CONFIRM_EXIT);
			}
			return false;
		}

		return super.onKeyDown(keyCode, event);
	}

	/**
	 * 
	 * @param isBack
	 *            back if true, others will forward
	 * @return true if navigative successfully/has historic results.
	 */
	private boolean naviHistoryPath(boolean isBack) {
		if (mPathBackHistory == null && isBack) {
			return false;
		}
		if (mPathForwardHistory == null && !isBack) {
			return false;
		}
		if (isBack) {
			if (mPathBackHistory.size() > 0) {
				mPathForwardHistory.push(mCurrentPath);
				mCurrentPath = mPathBackHistory.pop();
				Log.d(TAG, "back:" + mCurrentPath);
				loadDirs();
				return true;
			}
		} else if (mPathForwardHistory.size() > 0) {
			mPathBackHistory.push(mCurrentPath);
			mCurrentPath = mPathForwardHistory.pop();
			Log.d(TAG, "forward:" + mCurrentPath);
			loadDirs();
			return true;
		}

		return false;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.optionmenu, menu);

		return super.onCreateOptionsMenu(menu);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == ContentMenuActivity.OPERATOR_CUT) {
			//String file = data.getStringExtra(ContentMenuActivity.CURRENT_FILE);
		} else if (requestCode == ContentMenuActivity.OPERATOR_COPY) {
			//String file = data.getStringExtra(ContentMenuActivity.CURRENT_FILE);
		}
	}

	@Override
	protected void onResume() {
		super.onResume();
		Log.d(TAG, "onResume...");
		loadDirs();

	}

	public void onClick(View v) {
		if (!mIsNaviImageHide) {
			return;
		}

		if (v instanceof Button) {
			if (!mFileAdaper.isSelectEnable()) {
				if (!mFileAdaper.isSelectEnable()) {
					logHistory();
				}
				mCurrentPath = (String) v.getTag();
				Log.d(TAG, mCurrentPath);
				loadDirs();
			}
		} else if (v instanceof TextView) {
			Object o = v.getTag();
			if (TAG_NEW_DIR.equals(o)) {
				onNewFile(true);
			} else if (TAG_NEW_FILE.equals(o)) {
				// showDialog(DIALOG_NEXT_FILE);
				onNewFile(false);
			}
		} else {// file item
			if (!mFileAdaper.isSelectEnable()) {
				logHistory();
			}
			processFileItemClickEvent(v);
		}

	}

	private void onNewFile(boolean isFolder) {
		Intent intent = new Intent(this, NewFilesActivity.class);
		intent.putExtra(NewFilesActivity.CURRENT_PATH, mCurrentPath);
		int requestCode = isFolder ? NewFilesActivity.REQUEST_CODE_NEW_FOLDER
				: NewFilesActivity.REQUEST_CODE_NEW_FILE;
		intent.putExtra(NewFilesActivity.REQUEST_TYPE, requestCode);
		this.startActivityForResult(intent, requestCode);
		this.overridePendingTransition(R.anim.push_top_in, R.anim.push_top_out);
	}

	private void processFileItemClickEvent(View v) {
		if (mFileAdaper.isSelectEnable()) {
			SimpleFileListAdapter.ViewHolder holder = (SimpleFileListAdapter.ViewHolder) v
					.getTag();
			mFileAdaper.select(holder.itemIndex,
					!mFileAdaper.getSelected(holder.itemIndex));
			// holder.iconImage.invalidate();

			mFileAdaper.notifyDataSetChanged();
		} else {
			naviOrOpenFileWhenItemClick(v);
		}
	}

	private void naviOrOpenFileWhenItemClick(View v) {
		SimpleFileListAdapter.ViewHolder holder = (SimpleFileListAdapter.ViewHolder) v
				.getTag();
		if (holder.isFolder) {
			String fileName = holder.nameTxt;
			if (mCurrentPath.equals(File.separator)) {
				mCurrentPath = File.separator + fileName;
			} else {
				mCurrentPath = mCurrentPath + "/" + fileName;
			}
			ReadDirTask task = new ReadDirTask(mFileAdaper, this);
			task.execute(mCurrentPath);
			updatePath();
		} else {
			String file = mCurrentPath + "/"
					+ holder.nameTxt;
			
			DBUtil db = new DBUtil(this);
			Bookmark bm = new Bookmark();
			bm.name = holder.nameTxt;
			bm.path = mCurrentPath;
			bm.type = Bookmark.Types.MOST_USED;
			db.insert(bm);
			bm = null;
			db = null;
			FileTypes.openFile(this, new File(file));
			file = null;
			
		}

	}

	/**
	 * Add history to stack
	 */
	private void logHistory() {
		if (mPathBackHistory == null) {
			mPathBackHistory = new Stack<String>();
		}
		if (mPathForwardHistory == null) {
			mPathForwardHistory = new Stack<String>();
		}

		int size = mPathBackHistory.size();
		if (size > 0 && mPathBackHistory.peek().equals(mCurrentPath)) {
			return;
		}
		Log.d(TAG, "logHistory" + mCurrentPath);
		if (size >= COUNT_MAX_HISTORY) {
			mPathBackHistory.remove(0);
		}

		mPathForwardHistory.clear();
		mPathBackHistory.push(mCurrentPath);
	}

	private void initGlobalView() {
		LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mViewNavibar = inflater.inflate(R.layout.navibar, null);
		mViewSearchBar = inflater.inflate(R.layout.searchbar, null);
		mViewTitleBar = (ViewFlipper) findViewById(R.id.viewTitleBarGroup);
		mViewTitleBar.addView(mViewNavibar);
		mViewTitleBar.addView(mViewSearchBar);

		mBtnSearch = findViewById(R.id.btnTitleBarSwitch);

		mLayoutPathLayout = (LinearLayout) mViewNavibar
				.findViewById(R.id.layoutPath);
		mViewPathScrollView = (HorizontalScrollView) mViewNavibar
				.findViewById(R.id.viewPathScrollView);
		mDirList = (ListView) findViewById(R.id.dirs);
		mDirList.setOnTouchListener(this);
		mFileAdaper = new SimpleFileListAdapter(this);
		mPathAdapter = new PathAdapter(mLayoutPathLayout, this);
		mFileAdaper.setOnItemClickListener(this);
		mFileAdaper.setOnTouchListener(this);
		mFileAdaper.setOnLongClickListener(this);
		mPathAdapter.setListener(this);
		mDirList.setAdapter(mFileAdaper);

	}

	private void initNaviImage() {
		if (mNaviImage != null) {
			return;
		}
		mNaviImage = new ImageView(this);

		mNaviImage.setVisibility(View.GONE);
		WindowManager wm = this.getWindowManager();

		WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
				WindowManager.LayoutParams.TYPE_APPLICATION,
				WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
						| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
				PixelFormat.TRANSLUCENT);

		mNaviImage.setBackgroundColor(Color.TRANSPARENT);

		lp.gravity = Gravity.CENTER_VERTICAL | Gravity.TOP;

		// lp.x = 2;
		lp.y = 80;
		wm.addView(mNaviImage, lp);
	}

	/**
	 * 
	 * @param isLeft
	 * @param isNaviSuccess
	 */
	private void showNaviImage(boolean isLeft, boolean isNaviSuccess) {
		initNaviImage();
		if (isLeft && isNaviSuccess) {
			mNaviImage.setImageResource(R.drawable.back_96);
		} else if (isNaviSuccess) {
			mNaviImage.setImageResource(R.drawable.forward_96);
		} else {
			mNaviImage.setImageResource(R.drawable.stop_96);
		}
		mNaviImage.setVisibility(View.VISIBLE);
		mNaviImageAlpah = 255;
		mNaviImage.setAlpha(mNaviImageAlpah);
		mIsNaviImageHide = false;
		initHandler();

		new Thread(new Runnable() {
			public void run() {
				for (int i = 0; i < 25; i++) {
					mHandler.sendEmptyMessage(1);
					try {
						Thread.sleep(20);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();

	}

	private void initLocalView() {
		ImageButton backBtn = (ImageButton) findViewById(R.id.btnTitleBarSwitch);
		backBtn.setImageResource(R.drawable.filter_64);
		backBtn.setOnLongClickListener(this);
		backBtn.setTag(TAG_CONTROL_NAVI);
	}

	private void loadDirs() {

		if (mCurrentPath == null) {
			mCurrentPath = ROOT_PATH;
		}
		new ReadDirTask(mFileAdaper, this).execute(mCurrentPath);
		updatePath();

	}

	@Override
	public android.app.Dialog onCreateDialog(int which) {
		switch (which) {
		case DIALOG_CONFIRM_EXIT:
			// return Dialog.createExitConfirmDialog(this, this);
			return Dialog.createConfirmExitDialog(this, this);
		case DIALOG_CONTEXT_MENU:
			return Dialog.createContextMenuChoiceDialog(this,
					mCurrentSelectedIndex, this);
		case DIALOG_NEXT_FILE:
			return Dialog.createInputDialog(this);
		default:
			return null;
		}

	}

	private void updatePath() {
		mPathAdapter.setPath(mCurrentPath);
		final int width = mLayoutPathLayout.getWidth();
		mViewPathScrollView.post(new Runnable() {
			public void run() {
				mViewPathScrollView.smoothScrollTo(width, 0);
			}
		});
	}

	/**
	 * ReadDirTask callback function
	 */
	public void onFinished(FileDetails[] details) {

		View createDir = findViewById(R.id.viewEmptyFloderMsg);
		View createFile = findViewById(R.id.btnNewFile);
		if (details != null && details.length > 0) {
			createDir.setVisibility(View.GONE);
			createFile.setVisibility(View.GONE);
		} else {
			createDir.setVisibility(View.VISIBLE);
			createFile.setVisibility(View.VISIBLE);
		}
		//createDir.setTag(TAG_NEW_DIR);
		createFile.setTag(TAG_NEW_FILE);
		//createDir.setOnClickListener(this);
		createFile.setOnClickListener(this);

	}

	public boolean onLongClick(View v) {
		if (v instanceof ImageButton) { // navigate button and filter button
										// click
			ImageButton btn = (ImageButton) v;
			Integer tag = (Integer) btn.getTag();

			if (tag == TAG_CONTROL_NAVI) {
				btn.setImageResource(R.drawable.search_64);
				btn.setTag(TAG_CONTROL_SEARCH);
				mViewTitleBar.showNext();
			} else {
				btn.setImageResource(R.drawable.filter_64);
				btn.setTag(TAG_CONTROL_NAVI);
				mViewTitleBar.showPrevious();
			}
		} else if (mIsNaviImageHide) {// List Item click
			createContentMenu(v);
		}
		Log.d(TAG, "onLongClick");
		return false;
	}

	/**
	 * 
	 * @param v
	 *            click item
	 */
	private void createContentMenu(View v) {
		BaseFileListAdapter.ViewHolder holder = (ViewHolder) v.getTag();
		mCurrentSelectedIndex = holder.itemIndex;
		// showDialog(DIALOG_CONTEXT_MENU);
		Intent intent = new Intent(this, ContentMenuActivity.class);
		intent.putExtra(ContentMenuActivity.CURRENT_FILE, holder.nameTxt);
		intent.putExtra(ContentMenuActivity.CURRENT_PATH, mCurrentPath);
		startActivity(intent);
		overridePendingTransition(R.anim.push_top_in, R.anim.push_top_out);
	}

	public boolean onTouch(View v, MotionEvent event) {

		// Don't need to navigate when enable select mode.
		if (mFileAdaper.isSelectEnable()) {
			return false;
		}

		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			mOnTouchX = event.getX();
			mOnTouchY = event.getY();
			mIsTouchOnce = true;
		}

		Log.d(TAG, "mIsKeyDown:" + mIsTouchOnce);

		Log.d(TAG, "onTouch");
		float absY = Math.abs(mOnTouchY - event.getY());
		if (mOnTouchX - event.getX() > 100 && absY < 70) {
			if (mIsTouchOnce) {
				Log.d(TAG, "onTouch for onTouchListener: back");
				showNaviImage(true, naviHistoryPath(true));

				mIsTouchOnce = false;
			}
			return true;
		} else if (event.getX() - mOnTouchX > 100 && absY < 70) {
			if (mIsTouchOnce) {
				showNaviImage(false, naviHistoryPath(false));
				Log.d(TAG, "onTouch for onTouchListener: forward");
				mIsTouchOnce = false;
			}
			return true;
		}

		return false;
	}

	private void initHandler() {
		if (mHandler == null) {
			mHandler = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					if (msg.what == MSG_HIDE_NAVI_IMAGE) {

						if (mNaviImageAlpah > 20) {
							mNaviImageAlpah -= 10;
							mNaviImage.setAlpha(mNaviImageAlpah);
						} else {
							mIsNaviImageHide = true;
							mNaviImage.setVisibility(View.GONE);
						}
					}
				}
			};
		}
	}

	public void onExit() {
		if (mNaviImage != null) {
			WindowManager wm = this.getWindowManager();
			wm.removeViewImmediate(mNaviImage);// remove the subview for exit
												// activity

		}
		finish();
	}

	public void onCopy(int index) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onCopy");
	}

	public void onPaste(int index) {
		// TODO Auto-generated method stub

	}

	public void onMove(int index) {
		// TODO Auto-generated method stub

	}

	public void onRename(int index) {
		// TODO Auto-generated method stub

	}

	public void onDelete(int index) {
		// TODO Auto-generated method stub

	}

	public void onCut(int index) {
		// TODO Auto-generated method stub

	}

}